﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net;
using System.Net.Sockets;
using eLibCommon;
using System.IO;

namespace eLibServer.Core
{
  public class ClientHandler
  {
    private NetworkStream _stream;
    private byte[] _readBuffer = new byte[256];

    public IPEndPoint ClientEndPoint { get; set; }
    public List<string> ConversationHistory { get; set; }
    public TcpClient Client { get; set; }

    public event OnClientDisconnectHandler OnClientDisconnect;

    public ClientHandler(TcpClient client)
    {
      this.ClientEndPoint = (IPEndPoint) client.Client.RemoteEndPoint;
      this.Client = client;
      _stream = client.GetStream();

      this.ConversationHistory = new List<string>();
    }

    public void ThreadStartProc() 
    {
      this.ReadText();
    }

    public void ReadText()
    {
      if (_stream == null)
        return;

      _stream.BeginRead(_readBuffer
                       , 0
                       , _readBuffer.Length
                       , new AsyncCallback(this.OnReadComplete)
                       , null);
    }

    private void OnReadComplete(IAsyncResult ar)
    {
      string receiveString = string.Empty;
      try
      {
        int bytesRead = _stream.EndRead(ar);
        if (bytesRead > 0)
        {      
          receiveString = Encoding.ASCII.GetString(_readBuffer, 0, bytesRead);
          
          if (receiveString.EndsWith("\r\n"))
            receiveString = receiveString.Remove(receiveString.Length - 2);   

            this.EvaluateCommand(receiveString);
        }
      }
      catch (IOException)
      { 
      
      }
      finally
      {
        //if (this.Client.Connected)
          this.ReadText();
      }

    }

    public void WriteText(string message)
    {
      byte[] buffer = Encoding.ASCII.GetBytes(message);
      _stream.BeginWrite(buffer
                       , 0
                       , buffer.Length
                       , new AsyncCallback(this.OnWriteComplete)
                       , null);
    }

    private void OnWriteComplete(IAsyncResult ar)
    {
      if (_stream == null)
        return;

      int bytesWritten = _stream.EndRead(ar);
    }

    public void EvaluateCommand(string command)
    {
      this.ConversationHistory.Add(command);
      if (command == "HELLO")
      {
        this.WriteText("HELLO BACK\r\n");
        //AssignNewLocalPort(_localPort);
      }

      if (command == "PING")
      {
        this.WriteText("PONG\r\n");
      }  

      if (command == "BYE")
      {
        this.WriteText("DISCONNECTED\r\n");

        if (this.Client.Connected)
        {
          this.Client.Client.Shutdown(SocketShutdown.Both);
          this.Client.Client.Disconnect(false);
        }
        this.Client.Close();
        _stream = null;

        if (OnClientDisconnect != null)
          OnClientDisconnect(this, new OnClientDisconnectEventArgs(this.ClientEndPoint));
      }      

    }


  }
}
